<!DOCTYPE html>




<html class="theme-next pisces" lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">













<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">


















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">


<link href="https://fonts.loli.net/css?family=EB+Garamond:400,400i,700,700i|Noto+Serif+SC:400,500,700&display=swap&subset=chinese-simplified" rel="stylesheet">




  

<link href="//cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="FCN,">





  <link rel="alternate" href="/atom.xml" title="孔明の博客" type="application/atom+xml">






<meta name="description" content="与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类（全连接层＋softmax输出）不同，FCN可以接受任意尺寸的输入图像，采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸，从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。">
<meta name="keywords" content="FCN">
<meta property="og:type" content="article">
<meta property="og:title" content="【语义分割—FCN】Fully Convolutional Networks for Semantic Segmentation">
<meta property="og:url" content="https://gkm0120.github.io/p/17422.html">
<meta property="og:site_name" content="孔明の博客">
<meta property="og:description" content="与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类（全连接层＋softmax输出）不同，FCN可以接受任意尺寸的输入图像，采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸，从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20210224162304477.png?text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTgzOTAzOQ==,size_16,color_FFFFFF,t_70">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216205711829.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216205751863.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216211241841.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216211600272.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216211840841.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216211904944.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216211947750.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216212656280.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216212737440.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216212912662.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216212847238.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201217104755582.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201216213043826.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201212193122672.png?#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211161656386.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/2020121021242429.jpg#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211164945519.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211165028906.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211165500571.gif#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211165623297.gif#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211170423957.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/2020121021273060.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211170850429.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211171123951.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211171202448.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211171306283.png#pic_center">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20201211171358229.png#pic_center">
<meta property="og:updated_time" content="2021-03-31T01:36:18.004Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="【语义分割—FCN】Fully Convolutional Networks for Semantic Segmentation">
<meta name="twitter:description" content="与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类（全连接层＋softmax输出）不同，FCN可以接受任意尺寸的输入图像，采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸，从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。">
<meta name="twitter:image" content="https://img-blog.csdnimg.cn/20210224162304477.png?text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTgzOTAzOQ==,size_16,color_FFFFFF,t_70">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":true,"onmobile":true},
    fancybox: true,
    tabs: true,
    motion: {"enable":false,"async":false,"transition":{"post_block":"flipYIn","post_header":"perspectiveRightIn","post_body":"perspectiveLeftIn","coll_header":"perspectiveDownIn","sidebar":"perspectiveUpIn"}},
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://gkm0120.github.io/p/17422.html">





<!-- 设置文章需要密码访问 -->
<script>
    (function(){
        if(''){
            if (prompt('请输入文章密码') !== ''){
                alert('密码错误！');
                history.back();
            }
        }
    })();
</script>

  <title>【语义分割—FCN】Fully Convolutional Networks for Semantic Segmentation | 孔明の博客</title>

  

  








<link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css">
<link rel="stylesheet" href="/css/prism-line-numbers.css" type="text/css"></head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">

  

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <!--fork me from github-->
    <a href="https://github.com/gkm0120" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewbox="0 0 250 250" style="fill:#64CEAA; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">孔明の博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <h1 class="site-subtitle" itemprop="description"></h1>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            Archives
          </a>
        </li>
      

      
        <li class="menu-item menu-item-search">
          
            <a href="javascript:;" class="popup-trigger">
          
            
              <i class="menu-item-icon fa fa-search fa-fw"></i> <br>
            
            Search
          </a>
        </li>
      
    </ul>
  

  
    <div class="site-search">
      
  <div class="popup search-popup local-search-popup">
  <div class="local-search-header clearfix">
    <span class="search-icon">
      <i class="fa fa-search"></i>
    </span>
    <span class="popup-btn-close">
      <i class="fa fa-times-circle"></i>
    </span>
    <div class="local-search-input-wrapper">
      <input autocomplete="off" placeholder="Searching..." spellcheck="false" type="text" id="local-search-input">
    </div>
  </div>
  <div id="local-search-result"></div>
</div>



    </div>
  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://gkm0120.github.io/p/17422.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="戈孔明">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="孔明の博客">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">【语义分割—FCN】Fully Convolutional Networks for Semantic Segmentation</h2>
        

        <div class="post-meta">
          <span class="post-time">

             

             

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2020-12-11T20:31:40+08:00">
                2020-12-11
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/论文翻译/" itemprop="url" rel="index">
                    <span itemprop="name">论文翻译</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          <!--
          
          -->

          
            <span class="post-wordcount">
              
                
                  <span class="post-meta-divider">|</span>
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                <span title="Words count in article">
                  13.2k
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                <span title="Reading time">
                  48 分钟
                </span>
              
            </span>
          

          <!-- 隐藏文章内标题下，内容描述
          
          -->

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类（全连接层＋softmax输出）不同，FCN可以接受任意尺寸的输入图像，采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸，从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。</p>
<a id="more"></a>


<p><img src="https://img-blog.csdnimg.cn/20210224162304477.png?text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTgzOTAzOQ==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p>
<blockquote>
<p>论文：<a href="https://arxiv.org/abs/1411.4038v2" target="_blank" rel="noopener">Fully Convolutional Networks for Semantic Segmentation</a></p>
</blockquote>
<h1 id="一、论文翻译"><a href="#一、论文翻译" class="headerlink" title="一、论文翻译"></a>一、论文翻译</h1><h2 id="摘要"><a href="#摘要" class="headerlink" title="摘要"></a>摘要</h2><p>卷积网络在特征分层领域是非常强大的视觉模型。我们证明了经过端到端、像素到像素训练的卷积网络超过语义分割中最先进的技术。我们的核心观点是建立“全卷积”网络，输入任意尺寸，经过有效的推理和学习产生相应尺寸的输出。我们定义并指定全卷积网络的空间，解释它们在空间范围内dense prediction任务(预测每个像素所属的类别)和获取与先验模型联系的应用。我们改编当前的分类网络(AlexNet ,the VGG net, and GoogLeNet)到完全卷积网络和通过微调传递它们的学习表现到分割任务中。然后我们定义了一个跳跃式的架构，结合来自深、粗层的语义信息和来自浅、细层的表征信息来产生准确和精细的分割。我们的完全卷积网络成为了在PASCAL VOC最出色的分割方式（在2012年相对62.2%的平均IU提高了20%），NYUDv2，和SIFT Flow,对一个典型图像推理只需要花费不到0.2秒的时间。 </p>
<h2 id="1-引言"><a href="#1-引言" class="headerlink" title="1 引言"></a>1 引言</h2><p>卷积网络在识别领域前进势头很猛。卷积网不仅全图式的分类上有所提高 ,也在结构化输出的局部任务上取得了进步。包括在目标检测边界框 、部分和关键点预测和局部通信的进步。</p>
<p>在从粗糙到精细推理的进展中下一步自然是对每一个像素进行预测。早前的方法已经将卷积网络用于语义分割,其中每个像素被标记为其封闭对象或区域的类别，但是这项工作也有缺点。<br><img src="https://img-blog.csdnimg.cn/20201216205711829.png#pic_center" alt="在这里插入图片描述"></p>
<p>我们证明了经过 端到端 、像素到像素训练的的卷积网络超过语义分割中没有further machinery的最先进的技术。我们认为，这是第一次训练端到端(1)的FCN在像素级别的预测，而且来自监督式预处理(2)。全卷积在现有的网络基础上从任意尺寸的输入预测密集输出。学习和推理能在全图通过密集的前馈计算和反向传播一次执行。网内上采样层能在像素级别预测和通过下采样池化学习。</p>
<p>这种方法非常有效，无论是渐进地还是完全地，消除了在其他方法中的并发问题。Patchwise训练是常见的 ，但是缺少了全卷积训练的有效性。我们的方法不是利用预处理或者后期处理解决并发问题，包括超像素，proposals，或者对通过随机域事后细化或者局部分类。我们的模型通过重新解释分类网到全卷积网络和微调它们的学习表现将最近在分类上的成功 移植到dense prediction。与此相反，先前的工作应用的是小规模、没有超像素预处理的卷积网。</p>
<p>语义分割面临在语义和位置的内在张力问题：全局信息解决的“是什么”，而局部信息解决的是“在哪里”。深层特征通过非线性的局部到全局金字塔编码了位置和语义信息。我们在4.2节(见图3）定义了一种利用集合了深、粗层的语义信息和浅、细层的表征信息的特征谱的跨层架构。</p>
<p>在下一节，我们回顾深层分类网、FCNs和最近一些利用卷积网解决语义分割的相关工作。接下来的章节将解释FCN设计和密集预测权衡，介绍我们的网内上采样和多层结合架构，描述我们的实验框架。最后，我们展示了最先进技术在PASCAL VOC 2011-2, NYUDv2, 和SIFT Flow上的实验结果。</p>
<h2 id="2-相关工作"><a href="#2-相关工作" class="headerlink" title="2 相关工作"></a>2 相关工作</h2><p>我们的方法是基于最近深层网络在图像分类上的成功和转移学习。转移第一次被证明在各种视觉识别任务，然后是检测，不仅在实例还有融合proposal-classification模型的语义分割。我们现在重新构建和微调直接的、dense prediction语义分割的分类网。在这个框架里我们绘制FCNs的空间并将过去的或是最近的先验模型置于其中。</p>
<p>全卷积网络据我们所知，第一次将卷积网扩展到任意尺寸的输入的是Matan等人,它将经典的LeNet扩展到识别字符串的位数。因为他们的网络结构限制在一维的输入串，Matan等人利用译码器译码获得输出。Wolf和Platt将卷积网输出扩展到来检测邮政地址块的四角得分的二维图。这些先前工作做的是推理和用于检测的全卷积式学习。Ning等人定义了一种卷积网络用于秀丽线虫组织的粗糙的、多分类分割，基于全卷积推理。</p>
<p>全卷积计算也被用在现在的一些多层次的网络结构中。Sermanet等人的滑动窗口检测，Pinherio 和Collobert的语义分割，Eigen等人的图像修复都做了全卷积式推理。全卷积训练很少，但是被Tompson等人用来学习一种端到端的局部检测和姿态估计的空间模型非常有效，尽管他们没有解释或者分析这种方法。</p>
<p>此外，He等人在特征提取时丢弃了分类网的无卷积部分。他们结合proposals和空间金字塔池来产生一个局部的、固定长度的特征用于分类。尽管快速且有效，但是这种混合模型不能进行端到端的学习。</p>
<p>基于卷积网的dense prediction近期的一些工作已经将卷积网应用于dense prediction问题，包括Ning等人的语义分割,Farabet等人以及Pinheiro和Collobert；Ciresan等人的电子显微镜边界预测以及Ganin和Lempitsky的通过混合卷积网和最邻近模型的处理自然场景图像;还有Eigen等人的图像修复和深度估计。这些方法的相同点包括如下：</p>
<ul>
<li>限制容量和接收域的小模型</li>
<li>patchwise训练</li>
<li>超像素投影的预处理，随机场正则化、滤波或局部分类</li>
<li>输入移位和dense输出的隔行交错输出</li>
<li>多尺度金字塔处理</li>
<li>饱和双曲线正切非线性</li>
<li>集成<br>然而我们的方法确实没有这种机制。但是我们研究了patchwise训练 （3.4节）和从FCNs的角度出发的“shift-and-stitch”dense输出（3.2节）。我们也讨论了网内上采样（3.3节），其中Eigen等人的全连接预测是一个特例。</li>
</ul>
<p>和这些现有的方法不同的是，我们改编和扩展了深度分类架构，使用图像分类作为监督预处理，和从全部图像的输入和ground truths(用于有监督训练的训练集的分类准确性)通过全卷积微调进行简单且高效的学习。</p>
<p>Hariharan等人和Gupta等人也改编深度分类网到语义分割，但是也在混合proposal-classifier模型中这么做了。这些方法通过采样边界框和region proposal进行微调了R-CNN系统,用于检测、语义分割和实例分割。这两种办法都不能进行端到端的学习。他们分别在PASCAL VOC和NYUDv2实现了最好的分割效果，所以在第5节中我们直接将我们的独立的、端到端的FCN和他们的语义分割结果进行比较。</p>
<h2 id="3-全卷积网络"><a href="#3-全卷积网络" class="headerlink" title="3 全卷积网络"></a>3 全卷积网络</h2><p>卷积网的每层数据是一个$h\times w\times d$的三维数组，其中h和w是空间维度,d是特征或通道维数。第一层是像素尺寸为$h\times w$、颜色通道数为d的图像。高层中的locations和图像中它们连通的locations相对应，被称为接收域。</p>
<p>卷积网是以平移不变形作为基础的。其基本组成部分(卷积，池化和激励函数)作用在局部输入域，只依赖相对空间坐标。在特定层记$x_{ij}$为在坐标$(i,j)$的数据向量，在following layer有$y_{ij},y_{ij}$的计算公式如下:<br>$$y_{ij} = f_{ks}({x_{si+\delta i,sj+\delta j} }_{0\le \delta i,\delta j \le k})$$</p>
<p>其中k为卷积核尺寸，s是步长或下采样因素，$f_{ks}$决定了层的类型：一个卷积的矩阵乘或者是平均池化，用于最大池的最大空间值或者是一个激励函数的一个非线性elementwise，亦或是层的其他种类等等。</p>
<p>当卷积核尺寸和步长遵从转换规则，这个函数形式被表述为如下形式：<br>$$f_{ks} \circ g_{k^{\prime}s^{\prime}} = (f\circ g)_{k^{\prime}+(k-1)s,s^{\prime}}$$<br>当一个普通深度的网络计算一个普通的非线性函数，一个网络只有这种形式的层计算非线性滤波，我们称之为深度滤波或全卷积网络。FCN理应可以计算任意尺寸的输入并产生相应（或许重采样)空间维度的输出。</p>
<p>一个实值损失函数有FCN定义了task。如果损失函数是一个最后一层的空间维度总和,$\ell(x;\theta) = \sum_{ij} \ell^{\prime}(x_{ij};\theta)$，它的梯度将是它的每层空间组成梯度总和。所以在全部图像上的基于l的随机梯度下降计算将和基于$\ell^{\prime}$的梯度下降结果一样，将最后一层的所有接收域作为minibatch（分批处理）。在这些接收域重叠很大的情况下，前反馈计算和反向传播计算整图的叠层都比独立的patch-by-patch有效的多。</p>
<p>我们接下来将解释怎么将分类网络转换到能产生粗输出图的全卷积网络。对于像素级预测，我们需要连接这些粗略的输出结果到像素。3.2节描述了一种技巧，快速扫描因此被引入。我们通过将它解释为一个等价网络修正而获得了关于这个技巧的一些领悟。作为一个高效的替换，我们引入了去卷积层用于上采样见3.3节。在3.4节，我们考虑通过patchwise取样训练，便在4.3节证明我们的全图式训练更快且同样有效。</p>
<h3 id="3-1-改编分类用于dense-prediction"><a href="#3-1-改编分类用于dense-prediction" class="headerlink" title="3.1 改编分类用于dense prediction"></a>3.1 改编分类用于dense prediction</h3><p>典型的识别网络，包括LeNet, AlexNet, 和一些后续文章，表面上采用的是固定尺寸的输入产生了非空间的输出。这些网络的全连接层有确定的位数并丢弃空间坐标。然而，这些全连接层也被看做是覆盖全部输入域的核卷积。需要将它们加入到可以采用任何尺寸输入并输出分类图的全卷积网络中。这种转换如图2所示(相比之下，如Le等人的非卷积网，缺乏这种能力。)<br><img src="https://img-blog.csdnimg.cn/20201216205751863.png#pic_center" alt="在这里插入图片描述"><br>此外，当作为结果的图在特殊的输入patches上等同于原始网络的估计，计算是高度摊销的在那些patches的重叠域上。例如，当AlexNet花费了1.2ms（在标准的GPU上)推算一个227<em>227图像的分类得分，全卷积网络花费22ms从一张500</em>500的图像上产生一个10*10的输出网格，比朴素法快了5倍多。</p>
<p>这些卷积化模式的空间输出图可以作为一个很自然的选择对于dense问题，比如语义分割。每个输出单元ground truth可用，正推法和逆推法都是直截了当的，都利用了卷积的固有的计算效率(和可极大优化性)。对于AlexNet例子相应的逆推法的时间为单张图像时间2.4ms，全卷积的10*10输出图为37ms，结果是相对于顺推法速度加快了。</p>
<p>当我们将分类网络重新解释为任意输出尺寸的全卷积域输出图，输出维数也通过下采样显著的减少了。分类网络下采样使filter保持小规模同时计算要求合理。这使全卷积式网络的输出结果变得粗糙，通过输入尺寸因为一个和输出单元的接收域的像素步长等同的因素来降低它。</p>
<h3 id="3-2-Shift-and-stitch是滤波稀疏"><a href="#3-2-Shift-and-stitch是滤波稀疏" class="headerlink" title="3.2 Shift-and stitch是滤波稀疏"></a>3.2 Shift-and stitch是滤波稀疏</h3><p>dense prediction能从粗糙输出中通过从输入的平移版本中将输出拼接起来获得。如果输出是因为一个因子f降低采样，平移输入的x像素到左边，y像素到下面，一旦对于每个(x,y)满足$0\le x,y \le f-1$.处理$f^2$个输入，并将输出交错以便预测和它们接收域的中心像素一致。</p>
<p>考虑一个层（卷积或者池化）中的输入步长s,和后面的滤波权重为$f_{ij}$的卷积层（忽略不相关的特征维数）。设置更低层的输入步长到l上采样它的输出影响因子为s。然而，将原始的滤波和上采样的输出卷积并没有产生和shift-and-stitch相同的结果，因为原始的滤波只看得到（已经上采样）输入的简化的部分。为了重现这种技巧，通过扩大来稀疏滤波，如下:</p>
<p>$$<br>f_{i, j}^{\prime}=\begin{cases}<br>f_{i / s, j / s}, \quad \text { if } s \text { divides both } i \text { and } j \\<br>0, \quad \text { otherwise }<br>\end{cases}<br>$$</p>
<p>（$i$和$j$都是从0开始）。重现该技巧的全网输出需要重复一层一层放大这个filter知道所有的下采样被移除。（在练习中，处理上采样输入的下采样版本可能会更高效。）</p>
<p>在网内减少二次采样是一种折衷的做法：filter能看到更细节的信息，但是接受域更小而且需要花费很长时间计算。Shift-and -stitch技巧是另外一种折衷做法：输出更加密集且没有减小filter的接受域范围，但是相对于原始的设计filter不能感受更精细的信息。</p>
<p>尽管我们已经利用这个技巧做了初步的实验，但是我们没有在我们的模型中使用它。正如在下一节中描述的，我们发现从上采样中学习更有效和高效，特别是接下来要描述的结合了跨层融合。</p>
<h3 id="3-3-上采样是向后向卷积"><a href="#3-3-上采样是向后向卷积" class="headerlink" title="3.3 上采样是向后向卷积"></a>3.3 上采样是向后向卷积</h3><p>另一种连接粗糙输出到dense像素的方法就是插值法。比如，简单的双线性插值计算每个输出$y_{ij}$来自只依赖输入和输出单元的相对位置的线性图最近的四个输入。</p>
<p>从某种意义上，伴随因子f的上采样是对步长为1/f的分数式输入的卷积操作。只要f是整数，一种自然的方法进行上采样就是向后卷积（有时称为去卷积）伴随输出步长为f。这样的操作实现是不重要的，因为它只是简单的调换了卷积的顺推法和逆推法。所以上采样在网内通过计算像素级别的损失的反向传播用于端到端的学习。</p>
<p>需要注意的是去卷积滤波在这种层面上不需要被固定不变（比如双线性上采样）但是可以被学习。一堆反褶积层和激励函数甚至能学习一种非线性上采样。在我们的实验中，我们发现在网内的上采样对于学习dense prediction是快速且有效的。我们最好的分割架构利用了这些层来学习上采样用以微调预测，见4.2节。</p>
<h3 id="3-4-patchwise训练是一种损失采样"><a href="#3-4-patchwise训练是一种损失采样" class="headerlink" title="3.4 patchwise训练是一种损失采样"></a>3.4 patchwise训练是一种损失采样</h3><p>在随机优化中，梯度计算是由训练分布支配的。patchwise 训练和全卷积训练能被用来产生任意分布，尽管他们相对的计算效率依赖于重叠域和minibatch的大小。在每一个由所有的单元接受域组成的批次在图像的损失之下（或图像的集合）整张图像的全卷积训练等同于patchwise训练。当这种方式比patches的均匀取样更加高效的同时，它减少了可能的批次数量。然而在一张图片中随机选择patches可能更容易被重新找到。限制基于它的空间位置随机取样子集产生的损失（或者可以说应用输入和输出之间的DropConnect mask）排除来自梯度计算的patches。</p>
<p>如果保存下来的patches依然有重要的重叠，全卷积计算依然将加速训练。如果梯度在多重逆推法中被积累，batches能包含几张图的patches。patcheswise训练中的采样能纠正分类失调 和减轻密集空间相关性的影响。在全卷积训练中，分类平衡也能通过给损失赋权重实现，对损失采样能被用来标识空间相关。</p>
<p>我们研究了4.3节中的伴有采样的训练，没有发现对于dense prediction它有更快或是更好的收敛效果。全图式训练是有效且高效的。</p>
<h2 id="4-分割架构"><a href="#4-分割架构" class="headerlink" title="4 分割架构"></a>4 分割架构</h2><p>我们将ILSVRC分类应用到FCNs增大它们用于dense prediction结合网内上采样和像素级损失。我们通过微调为分割进行训练。接下来我们增加了跨层来融合粗的、语义的和局部的表征信息。这种跨层式架构能学习端到端来改善输出的语义和空间预测。</p>
<p>为此，我们训练和在PASCAL VOC 2011分割挑战赛中验证。我们训练逐像素的多项式逻辑损失和验证标准度量的在集合中平均像素交集还有基于所有分类上的平均接收，包括背景。这个训练忽略了那些在groud truth中被遮盖的像素（模糊不清或者很难辨认）。<br><img src="https://img-blog.csdnimg.cn/20201216211241841.png#pic_center" alt="在这里插入图片描述"></p>
<h3 id="4-1-从分类到dense-FCN"><a href="#4-1-从分类到dense-FCN" class="headerlink" title="4.1 从分类到dense FCN"></a>4.1 从分类到dense FCN</h3><p>我们在第3节中以卷积证明分类架构的。我们认为拿下了ILSVRC12的AlexNet架构和VGG nets 、GoogLeNet一样在ILSVRC14上表现的格外好。我们选择VGG 16层的网络，发现它和19层的网络在这个任务（分类）上相当。对于GoogLeNet,我们仅仅使用的最后的损失层，通过丢弃了最后的平均池化层提高了表现能力。我们通过丢弃最后的分类切去每层网络头，然后将全连接层转化成卷积层。我们附加了一个$1\times1$的、通道维数为21的卷积来预测每个PASCAL分类（包括背景）的得分在每个粗糙的输出位置，后面紧跟一个去卷积层用来双线性上采样粗糙输出到像素密集输出如3.3.节中描述。表1将初步验证结果和每层的基础特性比较。我们发现最好的结果在以一个固定的学习速率得到（最少175个epochs)。</p>
<p>从分类到分割的微调对每层网络有一个合理的预测。甚至最坏的模型也能达到大约75%的良好表现。内设分割的VGG网络（FCN-VGG16）已经在val上平均IU 达到了56.0取得了最好的成绩，相比于52.6。在额外数据上的训练将FCN-VGG16提高到59.4，将FCN-AlexNet提高到48.0。尽管相同的分类准确率，我们的用GoogLeNet并不能和VGG16的分割结果相比较。<br><img src="https://img-blog.csdnimg.cn/20201216211600272.png#pic_center" alt="在这里插入图片描述"></p>
<h3 id="4-2-结合“是什么”和“在哪里”"><a href="#4-2-结合“是什么”和“在哪里”" class="headerlink" title="4.2 结合“是什么”和“在哪里”"></a>4.2 结合“是什么”和“在哪里”</h3><p>我们定义了一个新的全卷积网用于结合了特征层级的分割并提高了输出的空间精度，见图3。当全卷积分类能被微调用于分割如4.1节所示，甚至在标准度量上得分更高，它们的输出不是很粗糙（见图4）。最后预测层的32像素步长限制了上采样输入的细节的尺寸。</p>
<p>我们提出增加结合了最后预测层和有更细小步长的更低层的跨层信息，将一个线划拓扑结构转变成DAG(有向无环图)，并且边界将从更底层向前跳跃到更高（图3）。因为它们只能获取更少的像素点，更精细的尺寸预测应该需要更少的层，所以从更浅的网中将它们输出是有道理的。结合了精细层和粗糙层让模型能做出遵从全局结构的局部预测。与Koenderick 和an Doorn的jet类似，我们把这种非线性特征层称之为deep jet。</p>
<p>我们首先将输出步长分为一半，通过一个16像素步长层预测。我们增加了一个1*1的卷积层在pool4的顶部来产生附加的类别预测。我们将输出和预测融合在conv7（fc7的卷积化）的顶部以步长32计算，通过增加一个2×的上采样层和预测求和（见图3）。我们初始化这个2×上采样到双线性插值，但是允许参数能被学习，如3.3节所描述、最后，步长为16的预测被上采样回图像，我们把这种网结构称为FCN-16s。FCN-16s用来学习端到端，能被最后的参数初始化。这种新的、在pool4上生效的参数是初始化为0 的，所以这种网结构是以未变性的预测开始的。这种学习速率是以100倍的下降的。</p>
<p>学习这种跨层网络能在3.0平均IU的有效集合上提高到62.4。图4展示了在精细结构输出上的提高。我们将这种融合学习和仅仅从pool4层上学习进行比较，结果表现糟糕，而且仅仅降低了学习速率而没有增加跨层，导致了没有提高输出质量的没有显著提高表现。</p>
<p>我们继续融合pool3和一个融合了pool4和conv7的2×上采样预测，建立了FCN-8s的网络结构。在平均IU上我们获得了一个较小的附加提升到62.7，然后发现了一个在平滑度和输出细节上的轻微提高。这时我们的融合提高已经得到了一个衰减回馈，既在强调了大规模正确的IU度量的层面上，也在提升显著度上得到反映，如图4所示，所以即使是更低层我们也不需要继续融合。</p>
<p>其他方式精炼化减少池层的步长是最直接的一种得到精细预测的方法。然而这么做对我们的基于VGG16的网络带来问题。设置pool5的步长到1，要求我们的卷积fc6核大小为14*14来维持它的接收域大小。另外它们的计算代价，通过如此大的滤波器学习非常困难。我们尝试用更小的滤波器重建pool5之上的层，但是并没有得到有可比性的结果；一个可能的解释是ILSVRC在更上层的初始化时非常重要的。</p>
<p>另一种获得精细预测的方法就是利用3.2节中描述的shift-and-stitch技巧。在有限的实验中，我们发现从这种方法的提升速率比融合层的方法花费的代价更高。</p>
<p><img src="https://img-blog.csdnimg.cn/20201216211840841.png#pic_center" alt="在这里插入图片描述"><br><img src="https://img-blog.csdnimg.cn/20201216211904944.png#pic_center" alt="在这里插入图片描述"></p>
<h3 id="4-3-实验框架"><a href="#4-3-实验框架" class="headerlink" title="4.3 实验框架"></a>4.3 实验框架</h3><p><strong>优化</strong> 我们利用momentum训练了GSD。我们利用了一个minibatch大小的20张图片，然后固定学习速率为$10^{-3},10^{-4}$，和$5^{-5}$用于FCN-AlexNet, FCN-VGG16,和FCN-GoogLeNet，通过各自的线性搜索选择。我们利用了0.9的momentum,权值衰减在$5^{-4}$或是$2^{-4}$，而且对于偏差的学习速率加倍了，尽管我们发现训练对单独的学习速率敏感。我们零初始化类的得分层，随机初始化既不能产生更好的表现也没有更快的收敛。Dropout被包含在用于原始分类的网络中。</p>
<p><strong>微调</strong> 我们通过反向传播微调整个网络的所有层。经过表2的比较，微调单独的输出分类表现只有全微调的70%。考虑到学习基础分类网络所需的时间，从scratch中训练不是可行的。（注意VGG网络的训练是阶段性的，当我们从全16层初始化后）。对于粗糙的FCN-32s，在单GPU上，微调要花费三天的时间，而且大约每隔一天就要更新到FCN-16s和FCN-8s版本。</p>
<p><img src="https://img-blog.csdnimg.cn/20201216211947750.png#pic_center" alt="在这里插入图片描述"></p>
<p><strong>patch取样</strong> 正如3.4节中解释的，我们的全图有效地训练每张图片batches到常规的、大的、重叠的patches网格。相反的，先前工作随机样本patches在一整个数据集，可能导致更高的方差batches，可能加速收敛。我们通过空间采样之前方式描述的损失研究这种折中，以1-p的概率做出独立选择来忽略每个最后层单元。为了避免改变有效的批次尺寸，我们同时以因子1/p增加每批次图像的数量。注意的是因为卷积的效率，在足够大的p值下，这种拒绝采样的形式依旧比patchwose训练要快（比如，根据3.1节的数量，最起码p&gt;0.2）图5展示了这种收敛的采样的效果。我们发现采样在收敛速率上没有很显著的效果相对于全图式训练，但是由于每个每个批次都需要大量的图像，很明显的需要花费更多的时间。 </p>
<p><strong>分类平衡</strong> 全卷积训练能通过按权重或对损失采样平衡类别。尽管我们的标签有轻微的不平衡（大约3/4是背景），我们发现类别平衡不是必要的。</p>
<p><strong>dense prediction</strong> 分数是通过网内的去卷积层上采样到输出维度。最后层去卷积滤波被固定为双线性插值，当中间采样层是被初始化为双线性上采样，然后学习。</p>
<p><strong>增强</strong> 扩大我们尝试通过随机反射扩大训练数据，”jettering”图像通过将它们在每个方向上转化成32像素（最粗糙预测的尺寸）。这并没有明显的改善。</p>
<p><strong>更多的训练数据</strong> PASCAL VOC 2011分割训练设置1112张图片的标签。Hariharan等人为一个更大的8498的PASCAL训练图片集合收集标签，被用于训练先前的先进系统,SDS。训练数据将FCV-VGG16得分提高了3.4个百分点到59.4。</p>
<p><strong>实现</strong> 所有的模型都是在单NVIDIA Tesla K40c上用Caffe训练和学习。</p>
<h2 id="5-结果"><a href="#5-结果" class="headerlink" title="5 结果"></a>5 结果</h2><p>我们训练FCN在语义分割和场景解析，研究了PASCAL VOC, NYUDv2和 SIFT Flow。尽管这些任务在以前主要是用在物体和区域上，我们都一律将它们视为像素预测。我们在这些数据集中都进行测试用来评估我们的FCN跨层式架构，然后对于NYUDv2将它扩展成一个多模型的输出，对于SIFT Flow则扩展成多任务的语义和集合标签。</p>
<p><strong>度量</strong> 我们从常见的语义分割和场景解析评估中提出四种度量，它们在像素准确率和在联合的区域交叉上是不同的。令$n_{ij}$为类别i的被预测为类别j的像素数量，有$n_{ij}$个不同的类别，令$t_i = \sum_j n_{ij}$<br>为类别i的像素总的数量。我们将计算：</p>
<ul>
<li><p>像素精度：$\sum_i n_{ii}/\sum_it_i$</p>
</li>
<li><p>平均准确度：$(1/n_{cl}) \sum_i n_{ii}/t_i$</p>
</li>
<li><p>平均交并比：$(1/n_{cl}) \sum_i n_{ii}/(t_i+\sum_j n_{ji}-n_{ii})$</p>
</li>
<li><p>频率加权交并比：$(\sum_k t_k)^{-1} \sum_i t_i n_{ii}/(t_i +\sum_j n_{ji}-n_{ii})$</p>
<p><strong>PASCAL VOC</strong> 表3给出了我们的FCN-8s的在PASCAL VOC2011和2012测试集上的表现，然后将它和之前的先进方法SDS和著名的R-CNN进行比较。我们在平均IU上取得了最好的结果相对提升了20%。推理时间被降低了114×（只有卷积网，没有proposals和微调)或者286×（全部都有）。<br><img src="https://img-blog.csdnimg.cn/20201216212656280.png#pic_center" alt="在这里插入图片描述"></p>
</li>
</ul>
<p><strong>NVUDv2</strong> 是一种通过利用Microsoft Kinect收集到的RGB-D数据集，含有已经被合并进Gupt等人的40类别的语义分割任务的pixelwise标签。我们报告结果基于标准分离的795张图片和654张测试图片。（注意：所有的模型选择将展示在PASCAL 2011 val上)。表4给出了我们模型在一些变化上的表现。首先我们在RGB图片上训练我们的未经修改的粗糙模型（FCN-32s）。为了添加深度信息，我们训练模型升级到能采用4通道RGB-Ds的输入（早期融合）。这提供了一点便利，也许是由于模型一直要传播有意义的梯度的困难。紧随Gupta等人的成功，我们尝试3维的HHA编码深度，只在这个信息上（即深度）训练网络，和RGB与HHA的“后期融合”一样来自这两个网络中的预测将在最后一层进行总结，结果的双流网络将进行端到端的学习。最后我们将这种后期融合网络升级到16步长的版本。</p>
<p><img src="https://img-blog.csdnimg.cn/20201216212737440.png#pic_center" alt="在这里插入图片描述"><br><strong>SIFT Flow</strong>是一个带有33语义范畴（“桥”、“山”、“太阳”）的像素标签的2688张图片的数据集和3个几何分类（“水平”、“垂直”和“sky”)一样。一个FCN能自然学习共同代表权，即能同时预测标签的两种类别。我们学习FCN-16s的一种双向版本结合语义和几何预测层和损失。这种学习模型在这两种任务上作为独立的训练模型表现很好，同时它的学习和推理基本上和每个独立的模型一样快。表5的结果显示，计算在标准分离的2488张训练图片和200张测试图片上计算，在这两个任务上都表现的极好。</p>
<h2 id="6-结论"><a href="#6-结论" class="headerlink" title="6 结论"></a>6 结论</h2><p>全卷积网络是模型非常重要的部分，是现代化分类网络中一个特殊的例子。认识到这个，将这些分类网络扩展到分割并通过多分辨率的层结合显著提高先进的技术，同时简化和加速学习和推理。<br><img src="https://img-blog.csdnimg.cn/20201216212912662.png#pic_center" alt="在这里插入图片描述"></p>
<p><img src="https://img-blog.csdnimg.cn/20201216212847238.png#pic_center" alt="在这里插入图片描述"><br><strong>鸣谢</strong> 这项工作有以下部分支持DARPA’s MSEE和SMISC项目，NSF awards IIS-1427425, IIS-1212798, IIS-1116411, 还有NSF GRFP,Toyota, 还有 Berkeley Vision和Learning Center。我们非常感谢NVIDIA捐赠的GPU。我们感谢Bharath Hariharan 和Saurabh Gupta的建议和数据集工具;我们感谢Sergio Guadarrama 重构了Caffe里的GoogLeNet;我们感谢Jitendra Malik的有帮助性评论;感谢Wei Liu指出了我们SIFT Flow平均IU计算上的一个问题和频率权重平均IU公式的错误。</p>
<h2 id="附录A-IU上界"><a href="#附录A-IU上界" class="headerlink" title="附录A IU上界"></a>附录A IU上界</h2><p>在这篇论文中，我们已经在平均IU分割度量上取到了很好的效果，即使是粗糙的语义预测。为了更好的理解这种度量还有关于这种方法的限制，我们在计算不同的规模上预测的表现的大致上界。我们通过下采样ground truth图像，然后再次对它们进行上采样，来模拟可以获得最好的结果，其伴随着特定的下采样因子。下表给出了不同下采样因子在PASCAL2011 val的一个子集上的平均IU。<img src="https://img-blog.csdnimg.cn/20201217104755582.png#pic_center" alt="在这里插入图片描述"></p>
<p>pixel-perfect预测很显然在取得最最好效果上不是必须的，而且，相反的，平均IU不是一个好的精细准确度的测量标准。</p>
<h2 id="附录B-更多的结果"><a href="#附录B-更多的结果" class="headerlink" title="附录B 更多的结果"></a>附录B 更多的结果</h2><p>我们将我们的FCN用于语义分割进行了更进一步的评估。PASCAL-Context提供了PASCAL VOC 2011的全部场景注释。有超过400中不同的类别，我们遵循了定义的被引用最频繁的59种类任务。我们分别训练和评估了训练集和val集。在表6中，我们将联合对象和Convolutional Feature Masking的stuff variation进行比较，后者是之前这项任务中最好的方法。FCN-8s在平均IU上得分为37.8，相对提高了20%<br><img src="https://img-blog.csdnimg.cn/20201216213043826.png#pic_center" alt="在这里插入图片描述"></p>
<h2 id="变更记录"><a href="#变更记录" class="headerlink" title="变更记录"></a>变更记录</h2><p>论文的arXiv版本保持着最新的修正和其他的相关材料，接下来给出一份简短的变更历史。v2 添加了附录A和附录B。修正了PASCAL的有效数量（之前一些val图像被包含在训练中），SIFT Flow平均IU（用的不是很规范的度量），还有频率权重平均IU公式的一个错误。添加了模型和更新时间数字来反映改进的实现的链接（公开可用的）。</p>
<hr>
<h1 id="二、论文解读"><a href="#二、论文解读" class="headerlink" title="二、论文解读"></a>二、论文解读</h1><p>图像分割的分类<br><img src="https://img-blog.csdnimg.cn/20201212193122672.png?#pic_center" alt="在这里插入图片描述"></p>
<ul>
<li><strong>image classification</strong> - 在已知类别数量的情况下，通过输入一张图片，来判断图片所属类别</li>
<li><strong>object localization</strong> - 判断图像中的目标具体在图像的什么位置，通常是以包围盒的(bounding box)形式进行定位</li>
<li><strong>semantic segmentation</strong> - 只标记语义, 也就是说分割出bottle、cube、cup类来</li>
<li><strong>instance segmentation</strong> - 标记实例和语义, 不仅要分割出cube这个类, 而且要分割出这个cube在哪, 也就是具体的实例</li>
</ul>
<h2 id="1-Introduction"><a href="#1-Introduction" class="headerlink" title="1.Introduction"></a>1.Introduction</h2><p>FCN对图像进行像素级的分类，解决了语义级别的图像分割（semantic segmentation）问题。与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类（全连接层＋softmax输出）不同，FCN可以接受任意尺寸的输入图像，采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸，从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。<br><img src="https://img-blog.csdnimg.cn/20201211161656386.png#pic_center" alt="在这里插入图片描述"></p>
<center>上图是语义分割所采用的全卷积网络(FCN)的结构示意图</center>


<h2 id="2-Fully-Convolutional-networks-amp-Architecture"><a href="#2-Fully-Convolutional-networks-amp-Architecture" class="headerlink" title="2.Fully Convolutional networks &amp; Architecture"></a>2.Fully Convolutional networks &amp; Architecture</h2><p><strong>核心思想</strong></p>
<ul>
<li><p>不含全连接层(fc)的全卷积(fully conv)网络。可适应任意尺寸输入。 </p>
</li>
<li><p>增大数据尺寸的反卷积(deconv)层。能够输出精细的结果。 </p>
</li>
<li><p>结合不同深度层结果的跳级(skip)结构。同时确保鲁棒性和精确性。</p>
<h3 id="2-1-卷积化-convolutionalization"><a href="#2-1-卷积化-convolutionalization" class="headerlink" title="2.1 卷积化(convolutionalization)"></a>2.1 卷积化(convolutionalization)</h3><p>通常CNN网络在卷积层之后会接上若干个全连接层, 将卷积层产生的特征图(feature map)映射成一个固定长度的特征向量。以AlexNet为代表的经典CNN结构适合于图像级的分类和回归任务，因为它们最后都得到整个输入图像的一个概率向量，比如AlexNet的ImageNet模型输出一个1000维的向量表示输入图像属于每一类的概率(softmax归一化)。<br><img src="https://img-blog.csdnimg.cn/2020121021242429.jpg#pic_center" alt="在这里插入图片描述"><br>如图所示：</p>
</li>
<li><p>在CNN中, 猫的图片输入到AlexNet, 得到一个长为1000的输出向量, 表示输入图像属于每一类的概率, 其中在“tabby cat”这一类统计概率最高, 用来做分类任务。</p>
</li>
<li><p><strong>FCN与CNN的区别</strong>在于把于CNN最后的全连接层转换成卷积层，输出的是一张已经Label好的图片, 而这个图片就可以做语义分割。</p>
</li>
</ul>
<p>CNN的强大之处在于它的<strong>多层结构能自动学习特征，并且可以学习到多个层次的特征</strong>：</p>
<ul>
<li><p>较浅的卷积层感知域较小，学习到一些局部区域的特征</p>
</li>
<li><p>较深的卷积层具有较大的感知域，能够学习到更加抽象一些的特征</p>
</li>
</ul>
<blockquote>
<p>为什么CNN对像素级别的分类很难?</p>
</blockquote>
<ul>
<li><strong>存储开销很大</strong>。例如对每个像素使用的图像块的大小为15x15，然后不断滑动窗口，每次滑动的窗口给CNN进行判别分类，因此则所需的存储空间根据滑动窗口的次数和大小急剧上升。</li>
<li><strong>计算效率低下</strong>。相邻的像素块基本上是重复的，针对每个像素块逐个计算卷积，这种计算也有很大程度上的重复。</li>
<li><strong>像素块大小的限制了感知区域的大小</strong>。通常像素块的大小比整幅图像的大小小很多，只能提取一些局部的特征，从而导致分类的性能受到限制。<blockquote>
<p>下面我们看一下是如何将<strong>全连接层</strong>和<strong>全卷积层</strong>的相互转化:</p>
</blockquote>
</li>
</ul>
<p>全连接层和卷积层之间唯一的不同就是<strong>卷积层中的神经元只与输入数据中的一个局部区域连接，并且在卷积列中的神经元共享参数</strong>。然而在两类层中，神经元都是计算点积，所以它们的函数形式是一样的。因此，将此两者相互转化是可能的：</p>
<ul>
<li><p><strong>对于任一个卷积层，都存在一个能实现和它一样的前向传播函数的全连接层</strong>。权重矩阵是一个巨大的矩阵，除了某些特定块，其余部分都是零。而在其中大部分块中，元素都是相等的。</p>
</li>
<li><p><strong>任何全连接层都可以被转化为卷积层</strong>。比如VGG16中第一个全连接层是25088∗4096的数据尺寸，将它转化为512∗7∗7∗4096的数据尺寸，即一个K=4096的全连接层，输入数据体的尺寸是7∗7∗512，这个全连接层可以被等效地看做一个F=7,P=0,S=1,K=4096的卷积层。<strong>换句话说，就是将滤波器的尺寸设置为和输入数据体的尺寸一致</strong>7∗7, 这样输出就变为1∗1∗4096, 本质上和全连接层的输出是一样的。</p>
</li>
<li><p>输出激活数据体深度是由卷积核的数目决定的(<strong>K=4096</strong>)</p>
</li>
</ul>
<p>在两种变换中，将全连接层转化为卷积层在实际运用中更加有用。假设一个卷积神经网络的输入是227x227x3的图像，一系列的卷积层和下采样层将图像数据变为尺寸为<strong>7x7x512</strong>的激活数据体, AlexNet的处理方式为使用了两个尺寸为4096的全连接层，最后一个有1000个神经元的全连接层用于计算分类评分。我们可以将这3个全连接层中的任意一个转化为卷积层：</p>
<ul>
<li>第一个连接区域是[7x7x512]的全连接层，令其滤波器尺寸为F=7,K=4096，这样输出数据体就为[1x1x4096]</li>
<li>第二个全连接层，令其滤波器尺寸为F=1,K=4096，这样输出数据体为[1x1x4096]</li>
<li>最后一个全连接层也做类似的，令其F=1,K=1000，最终输出为[1x1x1000]</li>
</ul>
<blockquote>
<p>fcn的输入图片为什么可以是任意大小呢？</p>
</blockquote>
<p>首先，我们来看传统CNN为什么需要固定输入图片大小。</p>
<p>对于CNN，一幅输入图片在经过卷积和pooling层时，这些层是不关心图片大小的。比如对于一个卷积层，$outputsize=(inputsize−kernelsize)/stride+1$，它并不关心inputsize多大，对于一个inputsize大小的输入feature map，滑窗卷积，输出outputsize大小的feature map即可。pooling层同理。但是在进入全连接层时，feature map（假设大小为n×n）要拉成一条向量，而向量中每个元素（共n×n个）作为一个结点都要与下一个层的所有结点（假设4096个）全连接，这里的权值个数是$4096×n×n$，而我们知道神经网络结构一旦确定，它的权值个数都是固定的，所以这个n不能变化，n是conv5的outputsize，所以层层向回看，每个outputsize都要固定，那每个inputsize都要固定，因此输入图片大小要固定。</p>
<blockquote>
<p>把全连接层的权重W重塑成卷积层的滤波器有什么好处呢?</p>
</blockquote>
<p>这样的转化可以在单个向前传播的过程中, 使得卷积网络在一张更大的输入图片上滑动，从而得到多个输出(可以理解为一个label map)</p>
<p>比如: 我们想让224×224尺寸的浮窗，以步长为32在384×384的图片上滑动，把每个经停的位置都带入卷积网络，最后得到6×6个位置的类别得分, 那么通过将全连接层转化为卷积层之后的运算过程为:</p>
<p>如果224×224的输入图片经过卷积层和下采样层之后得到了[7x7x512]的数组，那么，384×384的大图片直接经过同样的卷积层和下采样层之后会得到[12x12x512]的数组, 然后再经过上面由3个全连接层转化得到的3个卷积层，最终得到[6x6x1000]的输出((12 – 7)/1 + 1 = 6), 这个结果正是浮窗在原图经停的6×6个位置的得分。</p>
<p><strong>一个确定的CNN网络结构之所以要固定输入图片大小，是因为全连接层权值数固定，而该权值数和feature map大小有关</strong>, 但是FCN在CNN的基础上把1000个结点的全连接层改为含有1000个1×1卷积核的卷积层，经过这一层，还是得到二维的feature map，同样我们也不关心这个feature map大小, 所以对于输入图片的size并没有限制。</p>
<p>如下图所示，FCN将传统CNN中的全连接层转化成卷积层，对应CNN网络FCN把最后三层全连接层转换成为三层卷积层 :<br><img src="https://img-blog.csdnimg.cn/20201211164945519.png#pic_center" alt="在这里插入图片描述"></p>
<ol>
<li>全连接层转化为全卷积层 :在传统的CNN结构中，前5层是卷积层，第6层和第7层分别是一个长度为4096的一维向量，第8层是长度为1000的一维向量，分别对应1000个不同类别的概率。FCN将这3层表示为卷积层，卷积核的大小(通道数，宽，高) 分别为(4096,1,1)、(4096,1,1)、(1000,1,1)。看上去数字上并没有什么差别，但是卷积跟全连接是不一样的概念和计算过程，使用的是之前CNN已经训练好的权值和偏置，但是不一样的在于权值和偏置是有自己的范围，属于自己的一个卷积核</li>
<li>CNN中输入的图像大小是统一固定成<strong>227x227</strong>大小的图像，第一层pooling后为<strong>55x55</strong>，第二层pooling后图像大小为<strong>27x27</strong>，第五层pooling后的图像大小为<strong>13x13</strong>,而FCN输入的图像是H*W大小，第一层pooling后变为原图大小的1/2，第二层变为原图大小的1/4，第五层变为原图大小的1/8，第八层变为原图大小的1/16。</li>
<li>经过多次卷积和pooling以后，得到的图像越来越小，分辨率越来越低。其中图像到$H/32∗W/32$的时候图片是最小的一层时，所产生图叫做<strong>heatmap热图</strong>，热图就是我们最重要的高维特征图，得到高维特征的heatmap之后就是最重要的一步也是最后的一步对原图像进行<strong>upsampling</strong>，把图像进行放大几次到原图像的大小。<br><img src="https://img-blog.csdnimg.cn/20201211165028906.png#pic_center" alt="在这里插入图片描述"></li>
</ol>
<p>相较于使用被转化前的原始卷积神经网络对所有36个位置进行迭代计算优化模型，然后再对36个位置做预测，使用转化后的卷积神经网络进行一次前向传播计算要高效得多，因为36次计算都在共享计算资源。这一技巧在实践中经常使用，通常将一张图像尺寸变得更大，然后使用变换后的卷积神经网络来对空间上很多不同位置进行评价得到分类评分，然后在求这些分值的平均值。</p>
<h3 id="2-2-上采样-Upsampling"><a href="#2-2-上采样-Upsampling" class="headerlink" title="2.2 上采样(Upsampling)"></a>2.2 上采样(Upsampling)</h3><p>Upsampling的操作可以看成是反卷积(deconvolutional)，卷积运算的参数和CNN的参数一样是在训练FCN模型的过程中通过bp算法学习得到。反卷积层也是卷积层，不关心input大小，滑窗卷积后输出output。deconv并不是真正的deconvolution（卷积的逆变换），最近比较公认的叫法应该是transposed convolution，deconv的前向传播就是conv的反向传播。</p>
<ul>
<li>反卷积参数: 利用卷积过程filter的转置（实际上就是水平和竖直方向上翻转filter）作为计算卷积前的特征图</li>
<li>反卷积学习率为0</li>
</ul>
<p><a href="https://buptldy.github.io/2016/09/25/2016-09-25-cnn_vis/" target="_blank" rel="noopener">Ways for Visualizing Convolutional Networks</a></p>
<p>反卷积的运算如下所示:<br><strong>蓝色是反卷积层的input，绿色是反卷积层的output</strong></p>
<ol>
<li><strong>Full padding, transposed</strong><br><img src="https://img-blog.csdnimg.cn/20201211165500571.gif#pic_center" alt="在这里插入图片描述"></li>
</ol>
<ul>
<li>上图中$kernelsize=3,stride=1,padding=2$的反卷积，input是2×2, output是4×4</li>
</ul>
<ol start="2">
<li><strong>Zero padding, non-unit strides, transposed</strong></li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/20201211165623297.gif#pic_center" alt="在这里插入图片描述"></p>
<ul>
<li>图中$kernelsize=3,stride=2,padding=1$的反卷积，input feature map是3×3, 转化后是5×5, output是5×5<blockquote>
<p>怎么使反卷积的output大小和输入图片大小一致，从而得到pixel level prediction?</p>
</blockquote>
</li>
</ul>
<p>FCN里面全部都是卷积层（pooling也看成卷积），卷积层不关心input的大小，inputsize和outputsize之间存在线性关系。<br>假设图片输入为[n×n]大小，第一个卷积层输出map就为$conv1_{out}.size=(n−kernelsize)/stride+1$, 记做$conv1_{out}.size=f(n)$, 依次类推，$conv5_{out}.size=f(conv5_{in}.size)=f(…f(n))$, 反卷积是要使$n=f^{\prime}(conv5_{out}.size)$成立，要确定$f^{\prime}$，就需要设置deconvolution层的kernelsize，stride，padding，计算方法如下：</p>
<div class="highlight-wrap" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true" data-rel="COFFEESCRIPT"><figure class="iseeu highlight /coffeescript"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">layer {</span><br><span class="line"> name: <span class="string">"upsample"</span>, type: <span class="string">"Deconvolution"</span></span><br><span class="line"> bottom: <span class="string">"{{bottom_name}}"</span> top: <span class="string">"{{top_name}}"</span></span><br><span class="line"> convolution_param {</span><br><span class="line"> kernel_size: {{<span class="number">2</span> * factor - factor % <span class="number">2</span>}} stride: {{factor}}</span><br><span class="line"> num_output: {{C}} group: {{C}}</span><br><span class="line"> pad: {{ceil((factor - <span class="number">1</span>) / <span class="number">2.</span>)}}</span><br><span class="line"> weight_filler: { type: <span class="string">"bilinear"</span> } bias_term: <span class="literal">false</span></span><br><span class="line"> }</span><br><span class="line"> param { lr_mult: <span class="number">0</span> decay_mult: <span class="number">0</span> }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure></div>

<p><strong>factor</strong>是指反卷积之前的所有卷积pooling层的累积采样步长，卷积层使feature map变小，是因为stride，卷积操作造成的影响一般通过padding来消除，因此，累积采样步长factor就等于反卷积之前所有层的stride的乘积</p>
<h3 id="2-3-跳跃结构-Skip-Architecture"><a href="#2-3-跳跃结构-Skip-Architecture" class="headerlink" title="2.3 跳跃结构(Skip Architecture)"></a>2.3 跳跃结构(Skip Architecture)</h3><p>对CNN的结果做处理，得到了dense prediction，而作者在试验中发现，得到的分割结果比较粗糙，所以考虑加入更多前层的细节信息，也就是把倒数第几层的输出和最后的输出做一个fusion，实际上也就是加和：</p>
<p><img src="https://img-blog.csdnimg.cn/20201211170423957.png#pic_center" alt="在这里插入图片描述"><br>实验表明，这样的分割结果更细致更准确。在逐层fusion的过程中，做到第三行再往下，结果又会变差，所以作者做到这里就停了。</p>
<p>而不同的结构产生的结果对比如下:</p>
<p><img src="https://img-blog.csdnimg.cn/2020121021273060.png#pic_center" alt="在这里插入图片描述"></p>
<h2 id="3-model-training"><a href="#3-model-training" class="headerlink" title="3. model training"></a>3. model training</h2><ul>
<li><p>用AlexNet，VGG16或者GoogleNet训练好的模型做初始化，在这个基础上做fine-tuning，全部都fine-tuning，只需在末尾加上upsampling，参数的学习还是利用CNN本身的反向传播原理</p>
</li>
<li><p>采用whole image做训练，不进行patchwise sampling。实验证明直接用全图已经很effective and efficient</p>
</li>
<li><p>对class score的卷积层做全零初始化。随机初始化在性能和收敛上没有优势</p>
</li>
</ul>
<p><strong>FCN例子</strong>: 输入可为任意尺寸图像彩色图像；输出与输入尺寸相同，深度为：20类目标+背景=21，模型基于AlexNet</p>
<ul>
<li>蓝色：卷积层</li>
<li>绿色：Max Pooling层</li>
<li>黄色: 求和运算, 使用逐数据相加，把三个不同深度的预测结果进行融合：<strong>较浅的结果更为精细，较深的结果更为鲁棒</strong></li>
<li>灰色: 裁剪, 在融合之前，使用裁剪层统一两者大小, 最后裁剪成和输入相同尺寸输出</li>
<li>对于不同尺寸的输入图像，各层数据的尺寸（height，width）相应变化，深度（channel）不变</li>
</ul>
<p><img src="https://img-blog.csdnimg.cn/20201211170850429.png#pic_center" alt="在这里插入图片描述"></p>
<ul>
<li><p>全卷积层部分进行特征提取, 提取卷积层（3个蓝色层）的输出来作为预测21个类别的特征</p>
</li>
<li><p>图中虚线内是反卷积层的运算, 反卷积层（3个橙色层）可以把输入数据尺寸放大。和卷积层一样，升采样的具体参数经过训练确定</p>
</li>
</ul>
<ol>
<li>以经典的AlexNet分类网络为初始化。最后两级是全连接（红色），参数弃去不用<br><img src="https://img-blog.csdnimg.cn/20201211171123951.png#pic_center" alt="在这里插入图片描述"></li>
<li>从特征小图（16∗16∗4096）预测分割小图（16∗16∗21），之后直接升采样为大图。<br><img src="https://img-blog.csdnimg.cn/20201211171202448.png#pic_center" alt="在这里插入图片描述"></li>
</ol>
<ul>
<li>反卷积（橙色）的步长为32，这个网络称为FCN-32s</li>
</ul>
<ol start="3">
<li>升采样分为两次完成（橙色×2）, 在第二次升采样前，把第4个pooling层（绿色）的预测结果（蓝色）融合进来。使用跳级结构提升精确性<br><img src="https://img-blog.csdnimg.cn/20201211171306283.png#pic_center" alt="在这里插入图片描述"></li>
</ol>
<ul>
<li>第二次反卷积步长为16，这个网络称为FCN-16s</li>
</ul>
<ol start="4">
<li>升采样分为三次完成（橙色×3）, 进一步融合了第3个pooling层的预测结果<br><img src="https://img-blog.csdnimg.cn/20201211171358229.png#pic_center" alt="在这里插入图片描述"></li>
</ol>
<ul>
<li>第三次反卷积步长为8，记为FCN-8s。</li>
</ul>
<div class="highlight-wrap" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true" data-rel="PYTHON"><figure class="iseeu highlight /python"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"><span class="keyword">import</span> torch.nn <span class="keyword">as</span> nn</span><br><span class="line"><span class="keyword">import</span> torchvision</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">FCN8s</span><span class="params">(nn.Module)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, num_classes)</span>:</span></span><br><span class="line">        super(FCN8s, self).__init__()</span><br><span class="line">        vgg = torchvision.models.vgg16()</span><br><span class="line"></span><br><span class="line">        features = list(vgg.features.children())</span><br><span class="line"></span><br><span class="line">        self.padd = nn.ZeroPad2d([<span class="number">100</span>,<span class="number">100</span>,<span class="number">100</span>,<span class="number">100</span>])</span><br><span class="line"></span><br><span class="line">        self.pool3 = nn.Sequential(*features[:<span class="number">17</span>])</span><br><span class="line">        self.pool4 = nn.Sequential(*features[<span class="number">17</span>:<span class="number">24</span>])</span><br><span class="line">        self.pool5 = nn.Sequential(*features[<span class="number">24</span>:])</span><br><span class="line"></span><br><span class="line">        self.pool3_conv1x1 = nn.Conv2d(<span class="number">256</span>, num_classes, kernel_size=<span class="number">1</span>)</span><br><span class="line">        self.pool4_conv1x1 = nn.Conv2d(<span class="number">512</span>, num_classes, kernel_size=<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">        self.output5 = nn.Sequential(</span><br><span class="line">            nn.Conv2d(<span class="number">512</span>, <span class="number">4096</span>, kernel_size=<span class="number">7</span>),</span><br><span class="line">            nn.ReLU(inplace=<span class="literal">True</span>),</span><br><span class="line">            nn.Dropout(),</span><br><span class="line">            nn.Conv2d(<span class="number">4096</span>, <span class="number">4096</span>, kernel_size=<span class="number">1</span>),</span><br><span class="line">            nn.ReLU(inplace=<span class="literal">True</span>),</span><br><span class="line">            nn.Dropout(),</span><br><span class="line">            nn.Conv2d(<span class="number">4096</span>, num_classes, kernel_size=<span class="number">1</span>),</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        self.up_pool3_out = nn.ConvTranspose2d(num_classes, num_classes, kernel_size=<span class="number">16</span>, stride=<span class="number">8</span>)</span><br><span class="line">        self.up_pool4_out = nn.ConvTranspose2d(num_classes, num_classes, kernel_size=<span class="number">4</span>, stride=<span class="number">2</span>)</span><br><span class="line">        self.up_pool5_out = nn.ConvTranspose2d(num_classes, num_classes, kernel_size=<span class="number">4</span>, stride=<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">forward</span><span class="params">(self, x)</span>:</span></span><br><span class="line">        _,_, w, h = x.size()</span><br><span class="line"></span><br><span class="line">        x = self.padd(x)</span><br><span class="line">        pool3 = self.pool3(x)</span><br><span class="line">        pool4 = self.pool4(pool3)</span><br><span class="line">        pool5 = self.pool5(pool4)</span><br><span class="line"></span><br><span class="line">        output5 = self.up_pool5_out(self.output5(pool5))</span><br><span class="line"></span><br><span class="line">        pool4_out = self.pool4_conv1x1(<span class="number">0.01</span> * pool4)</span><br><span class="line">        output4 = self.up_pool4_out(pool4_out[:,:,<span class="number">5</span>:(<span class="number">5</span> + output5.size()[<span class="number">2</span>]) ,<span class="number">5</span>:(<span class="number">5</span> + output5.size()[<span class="number">3</span>])]+output5)</span><br><span class="line"></span><br><span class="line">        pool3_out = self.pool3_conv1x1(<span class="number">0.0001</span> * pool3)</span><br><span class="line">        output3 = self.up_pool3_out(pool3_out[:, :, <span class="number">9</span>:(<span class="number">9</span> + output4.size()[<span class="number">2</span>]), <span class="number">9</span>:(<span class="number">9</span> + output4.size()[<span class="number">3</span>])] + output4)</span><br><span class="line"></span><br><span class="line">        out = self.up_pool3_out(output3)</span><br><span class="line"></span><br><span class="line">        out = out[:, :, <span class="number">31</span>: (<span class="number">31</span> + h), <span class="number">31</span>: (<span class="number">31</span> + w)].contiguous()</span><br><span class="line">        <span class="keyword">return</span> out</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    model = FCN8s(num_classes=<span class="number">20</span>)</span><br><span class="line">    print(model)</span><br><span class="line"></span><br><span class="line">    input = torch.randn(<span class="number">1</span>,<span class="number">3</span>,<span class="number">224</span>,<span class="number">224</span>)</span><br><span class="line">    output = model(input)</span><br><span class="line">    print(output.shape)</span><br></pre></td></tr></tbody></table></figure></div>

<p><strong>其他参数</strong></p>
<ul>
<li>minibatch：20张图片</li>
<li>learning rate：0.001</li>
<li>初始化：分类网络之外的卷积层参数初始化为0</li>
<li>反卷积参数初始化为bilinear插值。最后一层反卷积固定位bilinear插值不做学习</li>
</ul>
<p>总体来说，本文的逻辑如下：</p>
<ul>
<li>想要精确预测每个像素的分割结果</li>
<li>必须经历从大到小，再从小到大的两个过程</li>
<li>在升采样过程中，分阶段增大比一步到位效果更好</li>
<li>在升采样的每个阶段，使用降采样对应层的特征进行辅助</li>
</ul>
<p><strong>缺点:</strong></p>
<ul>
<li><p>得到的结果还是不够精细。进行8倍上采样虽然比32倍的效果好了很多，但是上采样的结果还是比较模糊和平滑，对图像中的细节不敏感</p>
</li>
<li><p>对各个像素进行分类，没有充分考虑像素与像素之间的关系。忽略了在通常的基于像素分类的分割方法中使用的空间规整（spatial regularization）步骤，缺乏空间一致性。</p>
</li>
</ul>
<p>参考</p>
<ol>
<li><a href="https://www.cv-foundation.org/openaccess/content_cvpr_2015/html/Long_Fully_Convolutional_Networks_2015_CVPR_paper.html" target="_blank" rel="noopener">《Fully convolutional networks for semantic segmentation》</a></li>
<li><a href="https://www.cnblogs.com/xuanxufeng/p/6249834.html" target="_blank" rel="noopener">Fully Convolutional Networks for semantic Segmentation（深度学习经典论文翻译）</a></li>
<li><a href="https://www.cnblogs.com/gujianhan/p/6030639.html" target="_blank" rel="noopener">全卷积网络 FCN 详解</a></li>
<li><a href="https://blog.csdn.net/happyer88/article/details/47205839" target="_blank" rel="noopener">论文笔记《Fully Convolutional Networks for Semantic Segmentation》</a></li>
<li><a href="https://blog.csdn.net/taigw/article/details/51401448" target="_blank" rel="noopener">全卷积网络（FCN）与图像分割</a></li>
<li><a href="http://dgschwend.github.io/netscope/#/preset/fcn-16s" target="_blank" rel="noopener">FCN 16s</a></li>
<li><a href="https://github.com/shelhamer/fcn.berkeleyvision.org" target="_blank" rel="noopener">FCN模型和代码</a></li>
</ol>
<script>
        document.querySelectorAll('.github-emoji')
          .forEach(el => {
            if (!el.dataset.src) { return; }
            const img = document.createElement('img');
            img.style = 'display:none !important;';
            img.src = el.dataset.src;
            img.addEventListener('error', () => {
              img.remove();
              el.style.color = 'inherit';
              el.style.backgroundImage = 'none';
              el.style.background = 'none';
            });
            img.addEventListener('load', () => {
              img.remove();
            });
            document.body.appendChild(img);
          });
      </script>

        

      
    </div>

      <!-- 相关文章推荐 -->
     

    
    
    

    <div>
          
            

          
    </div>

    

    <div>
      
        <div>
    
        <div class="read-over">-------------------本文结束 <i class="fa fa-paw"></i> 感谢您的阅读-------------------</div>
    
</div>

      
    </div>

    
      <div>
        <div class="share_reward">
  <div></div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>Donate</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="/images/wechatpay.jpg" alt="戈孔明 WeChat Pay">
        <p>WeChat Pay</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="/images/alipay.jpg" alt="戈孔明 Alipay">
        <p>Alipay</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/FCN/" rel="tag"> <i class="fa fa-tag"></i> FCN</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/p/88644.html" rel="next" title="【图像分类—VGG】 Very Deep Convolutional Networks for Large-Scale Image Recognition">
                <i class="fa fa-chevron-left"></i> 【图像分类—VGG】 Very Deep Convolutional Networks for Large-Scale Image Recognition
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/p/19719.html" rel="prev" title="【图像分类—GoogLeNet Inception V1】Going Deeper With Convolutions">
                【图像分类—GoogLeNet Inception V1】Going Deeper With Convolutions <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
         <div data-weibo-title="分享到微博" data-qq-title="分享到QQ" data-douban-title="分享到豆瓣" class="social-share" data-disabled="qzone,google+,linkedin" data-description="Share.js - 一键分享到微博，QQ空间，腾讯微博，人人，豆瓣...">
   分享到：
</div>


      
    </div>
  </div>


          </div>
          


          

  
    <div id="gitalk-container"></div>

  





        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
      <div id="sidebar-dimmer"></div>
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            Table of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            Overview
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <a href="/">
              <img class="site-author-image" itemprop="image" src="/images/avatar.png" alt="戈孔明">
              </a>
            
              <p class="site-author-name" itemprop="name">戈孔明</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">26</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">9</span>
                  <span class="site-state-item-name">categories</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">26</span>
                  <span class="site-state-item-name">tags</span>
                </a>
              </div>
            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
              <!-- 为Hexo Next主题添加哈林摇特效  -->
              <a title="收藏到书签，偶尔High一下^_^" rel="alternate" class="mw-harlem_shake_slow wobble shake" href="javascript:void(0)" onclick="javascript:(    /*     * Copyright (C) 2015 Rocko (rocko.xyz) <rocko.zxp@gmail.com>     *     * Licensed under the Apache License, Version 2.0 (the 'License');     * you may not use this file except in compliance with the License.     * You may obtain a copy of the License at     *     *      http://www.apache.org/licenses/LICENSE-2.0     *     * Unless required by applicable law or agreed to in writing, software     * distributed under the License is distributed on an 'AS IS' BASIS,     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.     * See the License for the specific language governing permissions and     * limitations under the License.     */    function go() {        function c() {        var e = document.createElement('link');        e.setAttribute('type', 'text/css');        e.setAttribute('rel', 'stylesheet');        e.setAttribute('href', f);        e.setAttribute('class', l);        document.body.appendChild(e)    }     function h() {        var e = document.getElementsByClassName(l);        for (var t = 0; t < e.length; t++) {            document.body.removeChild(e[t])        }    }     function p() {        var e = document.createElement('div');        e.setAttribute('class', a);        document.body.appendChild(e);        setTimeout(function() {            document.body.removeChild(e)        }, 100)    }     function d(e) {        return {            height : e.offsetHeight,            width : e.offsetWidth        }    }     function v(i) {        var s = d(i);        return s.height > e &amp;&amp; s.height < n &amp;&amp; s.width > t &amp;&amp; s.width < r    }     function m(e) {        var t = e;        var n = 0;        while (!!t) {            n += t.offsetTop;            t = t.offsetParent        }        return n    }     function g() {        var e = document.documentElement;        if (!!window.innerWidth) {            return window.innerHeight        } else if (e &amp;&amp; !isNaN(e.clientHeight)) {            return e.clientHeight        }        return 0    }     function y() {        if (window.pageYOffset) {            return window.pageYOffset        }        return Math.max(document.documentElement.scrollTop, document.body.scrollTop)    }     function E(e) {        var t = m(e);        return t >= w &amp;&amp; t <= b + w    }     var songs = [                'http://s3.amazonaws.com/moovweb-marketing/playground/harlem-shake.mp3', 'http://www.ytmp3.cn/down/57563.mp3'  ];    function S() {        var e = document.getElementById('audio_element_id');        if(e != null){            var index = parseInt(e.getAttribute('curSongIndex'));            if(index > songs.length - 2) {                index = 0;            } else {                index++;            }            e.setAttribute('curSongIndex', index);            N();        }        e.src = i;        e.play()    }     function x(e) {        e.className += ' ' + s + ' ' + o    }     function T(e) {        e.className += ' ' + s + ' ' + u[Math.floor(Math.random() * u.length)]    }     function N() {        var e = document.getElementsByClassName(s);        var t = new RegExp('\\b' + s + '\\b');        for (var n = 0; n < e.length; ) {            e[n].className = e[n].className.replace(t, '')        }    }    function initAudioEle() {        var e = document.getElementById('audio_element_id');        if(e === null){            e = document.createElement('audio');            e.setAttribute('class', l);            e.setAttribute('curSongIndex', 0);            e.id = 'audio_element_id';            e.loop = false;            e.bgcolor = 0;            e.addEventListener('canplay', function() {            setTimeout(function() {                x(k)            }, 500);            setTimeout(function() {                N();                p();                for (var e = 0; e < O.length; e++) {                    T(O[e])                }            }, 15500)        }, true);        e.addEventListener('ended', function() {            N();            h();            go();        }, true);        e.innerHTML = ' <p>If you are reading this, it is because your browser does not support the audio element. We recommend that you get a new browser.</p> <p>';        document.body.appendChild(e);        }    }        initAudioEle();    var e = 30;    var t = 30;    var n = 350;    var r = 350;    var curSongIndex = parseInt(document.getElementById('audio_element_id').getAttribute('curSongIndex'));    var i = songs[curSongIndex];        var s = 'mw-harlem_shake_me';    var o = 'im_first';    var u = ['im_drunk', 'im_baked', 'im_trippin', 'im_blown'];    var a = 'mw-strobe_light';    var f = 'https://rocko.xyz/css/harlem-shake-style.css';        var l = 'mw_added_css';    var b = g();    var w = y();    var C = document.getElementsByTagName('*');    var k = null;    for (var L = 0; L < C.length; L++) {        var A = C[L];        if (v(A)) {            if (E(A)) {                k = A;                break            }        }    }    if (A === null) {        console.warn('Could not find a node of the right size. Please try a different page.');        return    }    c();    S();    var O = [];    for (var L = 0; L < C.length; L++) {        var A = C[L];        if (v(A)) {            O.push(A)        }    }    })()">
        <i class="fa fa-music"></i> High~
</a>

            </div>
          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a rel="external nofollow" href="https://github.com/gkm0120" target="_blank" title="GitHub">
                      
                        <i class="fa fa-fw fa-github"></i>GitHub</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a rel="external nofollow" href="mailto:gkm0120@163.com" target="_blank" title="E-Mail">
                      
                        <i class="fa fa-fw fa-envelope"></i>E-Mail</a>
                  </span>
                
            </div>
          

            <!--
            <div id="music163player">
                <iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=330 height=86 src="//music.163.com/outchain/player?type=2&id=1336790004&auto=1&height=66"></iframe>
            </div>
            -->

          
          
            <div class="cc-license motion-element" itemprop="license">
              <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow" class="cc-opacity" target="_blank">
                <img src="/images/cc-by-nc-sa.svg" alt="Creative Commons">
              </a>
            </div>
          

          
          
            <div class="links-of-blogroll motion-element links-of-blogroll-inline">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-link"></i>
                Links&nbsp;
                <i class="fa  fa-fw fa-link"></i>
              </div>
              <ul class="links-of-blogroll-list">
                
                  <li class="links-of-blogroll-item">
                    <a href="https://gkm0120.cn/" title="孔明の博客" rel="external nofollow" target="_blank">孔明の博客</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://hpcsiplab.hunnu.edu.cn/" title="LCSM" rel="external nofollow" target="_blank">LCSM</a>
                  </li>
                
              </ul>
            </div>
          

          <!--近期文章版块 began-->
          
          <!--近期文章版块 end-->

          
          
              <!-- 网站运行时间 -->
              <div id="days"></div>

<script language="javascript">
function show_date_time(){
window.setTimeout("show_date_time()", 1000);
BirthDay=new Date("03/15/2020 00:00:00");
today=new Date();
timeold=(today.getTime()-BirthDay.getTime());
sectimeold=timeold/1000
secondsold=Math.floor(sectimeold);
msPerDay=24*60*60*1000
e_daysold=timeold/msPerDay
daysold=Math.floor(e_daysold);
e_hrsold=(e_daysold-daysold)*24;
hrsold=setzero(Math.floor(e_hrsold));
e_minsold=(e_hrsold-hrsold)*60;
minsold=setzero(Math.floor((e_hrsold-hrsold)*60));
seconds=setzero(Math.floor((e_minsold-minsold)*60));
document.getElementById('days').innerHTML="已运行"+daysold+"天"+hrsold+"时"+minsold+"分"+seconds+"秒";
}
function setzero(i){
if (i<10)
{i="0" + i};
return i;
}
show_date_time();
</script>

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#一、论文翻译"><span class="nav-text">一、论文翻译</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#摘要"><span class="nav-text">摘要</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#1-引言"><span class="nav-text">1 引言</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-相关工作"><span class="nav-text">2 相关工作</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-全卷积网络"><span class="nav-text">3 全卷积网络</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-改编分类用于dense-prediction"><span class="nav-text">3.1 改编分类用于dense prediction</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-Shift-and-stitch是滤波稀疏"><span class="nav-text">3.2 Shift-and stitch是滤波稀疏</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-3-上采样是向后向卷积"><span class="nav-text">3.3 上采样是向后向卷积</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-4-patchwise训练是一种损失采样"><span class="nav-text">3.4 patchwise训练是一种损失采样</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-分割架构"><span class="nav-text">4 分割架构</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#4-1-从分类到dense-FCN"><span class="nav-text">4.1 从分类到dense FCN</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-2-结合“是什么”和“在哪里”"><span class="nav-text">4.2 结合“是什么”和“在哪里”</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-3-实验框架"><span class="nav-text">4.3 实验框架</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-结果"><span class="nav-text">5 结果</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-结论"><span class="nav-text">6 结论</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#附录A-IU上界"><span class="nav-text">附录A IU上界</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#附录B-更多的结果"><span class="nav-text">附录B 更多的结果</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#变更记录"><span class="nav-text">变更记录</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#二、论文解读"><span class="nav-text">二、论文解读</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-Introduction"><span class="nav-text">1.Introduction</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-Fully-Convolutional-networks-amp-Architecture"><span class="nav-text">2.Fully Convolutional networks &amp; Architecture</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-卷积化-convolutionalization"><span class="nav-text">2.1 卷积化(convolutionalization)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-上采样-Upsampling"><span class="nav-text">2.2 上采样(Upsampling)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-跳跃结构-Skip-Architecture"><span class="nav-text">2.3 跳跃结构(Skip Architecture)</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-model-training"><span class="nav-text">3. model training</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

      

      <!-- 标签云 -->
      <!--
      
      <script type="text/javascript" charset="utf-8" src="/js/tagcloud.js"></script>
      <script type="text/javascript" charset="utf-8" src="/js/tagcanvas.js"></script>
      <div class="widget-wrap">
      <h3 class="widget-title">Tag Cloud</h3>
      <div id="myCanvasContainer" class="widget tagcloud">
          <canvas width="250" height="250" id="resCanvas" style="width=100%">
              <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/AlexNet/">AlexNet</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/C/">C++</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Cauchy-问题/">Cauchy 问题</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Cohen-Sutherland/">Cohen-Sutherland</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/DES/">DES</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/FCN/">FCN</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/GoogLeNetV2/">GoogLeNetV2</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/GoogLeNetV3/">GoogLeNetV3</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/GoogleNetV1/">GoogleNetV1</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Hexo/">Hexo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Hill/">Hill</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Liang-Barsky/">Liang-Barsky</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Markdown/">Markdown</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/NiN/">NiN</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Nodejs/">Nodejs</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/OpenGL/">OpenGL</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ResNetV1/">ResNetV1</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/VGG/">VGG</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git/">git</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git配置/">git配置</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/latex/">latex</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/matlab函数/">matlab函数</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/matlab绘图/">matlab绘图</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/texlive安装/">texlive安装</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/数据集/">数据集</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/热传导方程/">热传导方程</a><span class="tag-list-count">1</span></li></ul>
          </canvas>
      </div>
      </div>
      
      -->
      <!-- 标签云 -->

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<div class="copyright">&copy; 2020 &mdash; <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
       <i class="fa fa-heartbeat"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">戈孔明</span>

  
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
    
    <span title="Site words total count">121.3k</span>
  
</div>

<!--









-->


        
<div class="busuanzi-count">
  <!--
  <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
  -->
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv">
      <i class="fa fa-user"></i>访问人数
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
      人次
    </span>
  

  
    <span class="site-pv">
      <i class="fa fa-eye"></i>总访问量
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
      次
    </span>
  
</div>








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
          <span id="scrollpercent"><span>0</span>%</span>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="//cdn.jsdelivr.net/npm/jquery@2.1.3/dist/jquery.min.js"></script>
  

  
  
    <script type="text/javascript" src="//cdn.jsdelivr.net/fastclick/1.0.6/fastclick.min.js"></script>
  

  
  
    <script type="text/javascript" src="//cdn.jsdelivr.net/jquery.lazyload/1.9.3/jquery.lazyload.min.js"></script>
  

  
  
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/velocity-animate@1.2.1/velocity.min.js"></script>
  

  
  
    <script type="text/javascript" src="//cdn.jsdelivr.net/npm/velocity-animate@1.2.1/velocity.ui.min.js"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  













  <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
  <script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>
  <script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
  <script type="text/javascript">
        var gitalk = new Gitalk({
          clientID: '6a4708bb548d9ee47cfd',
          clientSecret: '29a20b874fd47e6c4d1229c036d5e37beeda813d',
          repo: 'gkm0120.github.io',
          owner: 'gkm0120',
          admin: ['gkm0120'],
          id: md5(window.location.pathname),
          distractionFreeMode: 'true'
        })
        gitalk.render('gitalk-container')
       </script>



  

  <script type="text/javascript">
    // Popup Window;
    var isfetched = false;
    var isXml = true;
    // Search DB path;
    var search_path = "search.xml";
    if (search_path.length === 0) {
      search_path = "search.xml";
    } else if (/json$/i.test(search_path)) {
      isXml = false;
    }
    var path = "/" + search_path;
    // monitor main search box;

    var onPopupClose = function (e) {
      $('.popup').hide();
      $('#local-search-input').val('');
      $('.search-result-list').remove();
      $('#no-result').remove();
      $(".local-search-pop-overlay").remove();
      $('body').css('overflow', '');
    }

    function proceedsearch() {
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay"></div>')
        .css('overflow', 'hidden');
      $('.search-popup-overlay').click(onPopupClose);
      $('.popup').toggle();
      var $localSearchInput = $('#local-search-input');
      $localSearchInput.attr("autocapitalize", "none");
      $localSearchInput.attr("autocorrect", "off");
      $localSearchInput.focus();
    }

    // search function;
    var searchFunc = function(path, search_id, content_id) {
      'use strict';

      // start loading animation
      $("body")
        .append('<div class="search-popup-overlay local-search-pop-overlay">' +
          '<div id="search-loading-icon">' +
          '<i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>' +
          '</div>' +
          '</div>')
        .css('overflow', 'hidden');
      $("#search-loading-icon").css('margin', '20% auto 0 auto').css('text-align', 'center');

      $.ajax({
        url: path,
        dataType: isXml ? "xml" : "json",
        async: true,
        success: function(res) {
          // get the contents from search data
          isfetched = true;
          $('.popup').detach().appendTo('.header-inner');
          var datas = isXml ? $("entry", res).map(function() {
            return {
              title: $("title", this).text(),
              content: $("content",this).text(),
              url: $("url" , this).text()
            };
          }).get() : res;
          var input = document.getElementById(search_id);
          var resultContent = document.getElementById(content_id);
          var inputEventFunction = function() {
            var searchText = input.value.trim().toLowerCase();
            var keywords = searchText.split(/[\s\-]+/);
            if (keywords.length > 1) {
              keywords.push(searchText);
            }
            var resultItems = [];
            if (searchText.length > 0) {
              // perform local searching
              datas.forEach(function(data) {
                var isMatch = false;
                var hitCount = 0;
                var searchTextCount = 0;
                var title = data.title.trim();
                var titleInLowerCase = title.toLowerCase();
                var content = data.content.trim().replace(/<[^>]+>/g,"");
                var contentInLowerCase = content.toLowerCase();
                var articleUrl = decodeURIComponent(data.url);
                var indexOfTitle = [];
                var indexOfContent = [];
                // only match articles with not empty titles
                if(title != '') {
                  keywords.forEach(function(keyword) {
                    function getIndexByWord(word, text, caseSensitive) {
                      var wordLen = word.length;
                      if (wordLen === 0) {
                        return [];
                      }
                      var startPosition = 0, position = [], index = [];
                      if (!caseSensitive) {
                        text = text.toLowerCase();
                        word = word.toLowerCase();
                      }
                      while ((position = text.indexOf(word, startPosition)) > -1) {
                        index.push({position: position, word: word});
                        startPosition = position + wordLen;
                      }
                      return index;
                    }

                    indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false));
                    indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false));
                  });
                  if (indexOfTitle.length > 0 || indexOfContent.length > 0) {
                    isMatch = true;
                    hitCount = indexOfTitle.length + indexOfContent.length;
                  }
                }

                // show search results

                if (isMatch) {
                  // sort index by position of keyword

                  [indexOfTitle, indexOfContent].forEach(function (index) {
                    index.sort(function (itemLeft, itemRight) {
                      if (itemRight.position !== itemLeft.position) {
                        return itemRight.position - itemLeft.position;
                      } else {
                        return itemLeft.word.length - itemRight.word.length;
                      }
                    });
                  });

                  // merge hits into slices

                  function mergeIntoSlice(text, start, end, index) {
                    var item = index[index.length - 1];
                    var position = item.position;
                    var word = item.word;
                    var hits = [];
                    var searchTextCountInSlice = 0;
                    while (position + word.length <= end && index.length != 0) {
                      if (word === searchText) {
                        searchTextCountInSlice++;
                      }
                      hits.push({position: position, length: word.length});
                      var wordEnd = position + word.length;

                      // move to next position of hit

                      index.pop();
                      while (index.length != 0) {
                        item = index[index.length - 1];
                        position = item.position;
                        word = item.word;
                        if (wordEnd > position) {
                          index.pop();
                        } else {
                          break;
                        }
                      }
                    }
                    searchTextCount += searchTextCountInSlice;
                    return {
                      hits: hits,
                      start: start,
                      end: end,
                      searchTextCount: searchTextCountInSlice
                    };
                  }

                  var slicesOfTitle = [];
                  if (indexOfTitle.length != 0) {
                    slicesOfTitle.push(mergeIntoSlice(title, 0, title.length, indexOfTitle));
                  }

                  var slicesOfContent = [];
                  while (indexOfContent.length != 0) {
                    var item = indexOfContent[indexOfContent.length - 1];
                    var position = item.position;
                    var word = item.word;
                    // cut out 100 characters
                    var start = position - 20;
                    var end = position + 80;
                    if(start < 0){
                      start = 0;
                    }
                    if (end < position + word.length) {
                      end = position + word.length;
                    }
                    if(end > content.length){
                      end = content.length;
                    }
                    slicesOfContent.push(mergeIntoSlice(content, start, end, indexOfContent));
                  }

                  // sort slices in content by search text's count and hits' count

                  slicesOfContent.sort(function (sliceLeft, sliceRight) {
                    if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) {
                      return sliceRight.searchTextCount - sliceLeft.searchTextCount;
                    } else if (sliceLeft.hits.length !== sliceRight.hits.length) {
                      return sliceRight.hits.length - sliceLeft.hits.length;
                    } else {
                      return sliceLeft.start - sliceRight.start;
                    }
                  });

                  // select top N slices in content

                  var upperBound = parseInt('1');
                  if (upperBound >= 0) {
                    slicesOfContent = slicesOfContent.slice(0, upperBound);
                  }

                  // highlight title and content

                  function highlightKeyword(text, slice) {
                    var result = '';
                    var prevEnd = slice.start;
                    slice.hits.forEach(function (hit) {
                      result += text.substring(prevEnd, hit.position);
                      var end = hit.position + hit.length;
                      result += '<b class="search-keyword">' + text.substring(hit.position, end) + '</b>';
                      prevEnd = end;
                    });
                    result += text.substring(prevEnd, slice.end);
                    return result;
                  }

                  var resultItem = '';

                  if (slicesOfTitle.length != 0) {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + highlightKeyword(title, slicesOfTitle[0]) + "</a>";
                  } else {
                    resultItem += "<li><a href='" + articleUrl + "' class='search-result-title'>" + title + "</a>";
                  }

                  slicesOfContent.forEach(function (slice) {
                    resultItem += "<a href='" + articleUrl + "'>" +
                      "<p class=\"search-result\">" + highlightKeyword(content, slice) +
                      "...</p>" + "</a>";
                  });

                  resultItem += "</li>";
                  resultItems.push({
                    item: resultItem,
                    searchTextCount: searchTextCount,
                    hitCount: hitCount,
                    id: resultItems.length
                  });
                }
              })
            };
            if (keywords.length === 1 && keywords[0] === "") {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-search fa-5x" /></div>'
            } else if (resultItems.length === 0) {
              resultContent.innerHTML = '<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'
            } else {
              resultItems.sort(function (resultLeft, resultRight) {
                if (resultLeft.searchTextCount !== resultRight.searchTextCount) {
                  return resultRight.searchTextCount - resultLeft.searchTextCount;
                } else if (resultLeft.hitCount !== resultRight.hitCount) {
                  return resultRight.hitCount - resultLeft.hitCount;
                } else {
                  return resultRight.id - resultLeft.id;
                }
              });
              var searchResultList = '<ul class=\"search-result-list\">';
              resultItems.forEach(function (result) {
                searchResultList += result.item;
              })
              searchResultList += "</ul>";
              resultContent.innerHTML = searchResultList;
            }
          }

          if ('auto' === 'auto') {
            input.addEventListener('input', inputEventFunction);
          } else {
            $('.search-icon').click(inputEventFunction);
            input.addEventListener('keypress', function (event) {
              if (event.keyCode === 13) {
                inputEventFunction();
              }
            });
          }

          // remove loading animation
          $(".local-search-pop-overlay").remove();
          $('body').css('overflow', '');

          proceedsearch();
        }
      });
    }

    // handle and trigger popup window;
    $('.popup-trigger').click(function(e) {
      e.stopPropagation();
      if (isfetched === false) {
        searchFunc(path, 'local-search-input', 'local-search-result');
      } else {
        proceedsearch();
      };
    });

    $('.popup-btn-close').click(onPopupClose);
    $('.popup').click(function(e){
      e.stopPropagation();
    });
    $(document).on('keyup', function (event) {
      var shouldDismissSearchPopup = event.which === 27 &&
        $('.search-popup').is(':visible');
      if (shouldDismissSearchPopup) {
        onPopupClose();
      }
    });
  </script>





  

  

  
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https') {
        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
    }
    else {
        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>


  
  
  
  <link rel="stylesheet" href="/lib/needsharebutton/needsharebutton.css">

  
  
  <script src="/lib/needsharebutton/needsharebutton.js"></script>

  <script>
    
    
  </script>

  

  
  
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script type="text/javascript" src="//cdn.bootcss.com/mathjax/2.7.1/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
  


  

  


  <!-- Tidio 在线联系功能、鼠标点击特效、页面反馈...-->
  


  










  <script src="/js/src/activate-power-mode.min.js"></script>
  <script>
    POWERMODE.colorful = true;
    POWERMODE.shake = false;
    document.body.addEventListener('input', POWERMODE);
  </script>



  <!-- 看板娘 -->
  <!--  -->

  <!-- 看板娘 -->
  <script async src="/live2d-widget/autoload.js"></script>

  
      <!-- aplayer音频播放 -->
      <link rel="stylesheet" href="/dist/APlayer.min.css">
      <div id="aplayer"></div>
      <script type="text/javascript" src="/dist/APlayer.min.js"></script>
      <script type="text/javascript" src="/dist/music.js"></script>
  

  <!-- 代码块复制功能 -->
  <script type="text/javascript" src="/js/src/clipboard.min.js"></script>
  <script type="text/javascript" src="/js/src/clipboard-use.js"></script>

  <!--share.js-->
  <link rel="stylesheet" href="/sharejs/css/share.min.css">
  <script src="/sharejs/js/social-share.min.js"></script>

  <!-- 模仿知乎卡片样式链接、崩溃欺骗特效 -->
  <!--<script type="text/javascript" src="/js/src/linkcard.js"></script>-->

  <!--崩溃欺骗 放在js文件最后-->
  <!--<script type="text/javascript" src="/js/src/crash_cheat.js"></script>-->



</body>
</html>
